﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Sahit.iSoilHotel.Infrastructure.Core.Helper;

namespace Sahit.iSoilHotel.Domain.Seedwork
{
    public abstract class Entity
    {
        #region Members

        private Guid Id;
        private int? requestHashCode;

        #endregion

        #region Properties

        public virtual Guid ID
        {
            get
            {
                return this.Id;
            }
            protected set
            {
                this.Id = value;
            }
        }

        #endregion
      
        #region Public Methods

        public bool isTransient()
        {
            return this.Id == Guid.Empty;
        }

        public void GenerateNewIdentity()
        {
            if (isTransient())
                this.Id = IdentityGeneratorHelper.NewSequentialGuid();
        }

        public void ChangeCurrentIdentity(Guid identity)
        {
            if (identity != Guid.Empty)
                this.Id = identity;
        }

       #endregion

        #region Override Methods

        public override bool Equals(object obj)
        {
            if (obj == null || !(obj is Entity))
                return false;
            if(Object.ReferenceEquals(this,obj))
                return true;
            Entity item = obj as Entity;
            if (item.isTransient() || this.isTransient())
                return false;
            return item.Id == this.Id;
        }

        public override int GetHashCode()
        {
            if (!isTransient())
            {
                if (!requestHashCode.HasValue)
                    requestHashCode = this.Id.GetHashCode() ^ 31;// XOR for random distribution (http://blogs.msdn.com/b/ericlippert/archive/2011/02/28/guidelines-and-rules-for-gethashcode.aspx)
                return requestHashCode.Value;
            }
            return base.GetHashCode();
        }

        public static bool operator ==(Entity left, Entity right)
        {
            if (Object.Equals(left, null))
                return Object.Equals(right, null);
            return left.Equals(right);
        }

        public static bool operator !=(Entity left, Entity right)
        {
            return !(left == right);
        }

        #endregion
    }
}
